package com.kehutong.repair.service.admin;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.threadpool.ThreadPool;
import org.coraframework.util.Objects;

import com.kehutong.common.DoveClient;
import com.kehutong.common.util.Token;
import com.kehutong.repair.admin.AdminRepairsController;
import com.kehutong.repair.entity.Remark;
import com.kehutong.repair.entity.Repairs;
import com.kehutong.repair.entity.RepairsType;
import com.kehutong.repair.entity.RollOutDetail;
import com.kehutong.repair.enums.RepairsStatus;
import com.kehutong.repair.utils.RepairsUtils;
import com.kehutong.repair.utils.SendMessageUtils;

@WebService("/repairs/admin/service")
public class AdminRepairsService {

    private static final Logger logger = LoggerFactory.getLogger(AdminRepairsController.class);

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private DoveClient doveClient;
    @Inject
    private SendMessageUtils sendMessageUtils;
    @Inject
    private ThreadPool threadPool;

    @ReqMapping("/list")
    public Page<Repairs> list(Token token, JSONObject jsonObject) throws Exception {
        boolean isAll = jsonObject.getBoolean("isAll");
        boolean isTimeOut = jsonObject.getBoolean("isTimeOut");

        if(!isAll){
            jsonObject.put("exeEmployeeNo", token.getUuid());
            jsonObject.put("attnEmployeeNo", token.getUuid());
            jsonObject.put("employeeNo", token.getUuid());
        }

        final FindPage<Repairs> find = jdbcSession.findPage(Repairs.class)
                .eq(jsonObject, "id", "typeId", "createBy", "contactMobile", "source","repairsStatus", "companyNo", "type","noId","communityNo")
                .like(jsonObject,"detail")
                .between("createTime", jsonObject, "beginTime", "endTime");

        if (isTimeOut) {
            List<String> repairsStatus = new ArrayList<>();
            repairsStatus.add("1");
            repairsStatus.add("2");
            find.in("repairsStatus", repairsStatus)
                    .minEq("timeOut", LocalDateTime.now().toString());
        }

        if(Objects.nonNull(jsonObject.getBoolean("dateStatus"))){
            if(!jsonObject.getBoolean("dateStatus")){
                find.max("timeOut",LocalDateTime.now().toString());
            }else{
                find.minEq("timeOut",LocalDateTime.now().toString());
            }
        }

        String active = jsonObject.getString("active");
        if(Objects.isEmpty(active)){
            if(Objects.nonEmpty(jsonObject.getString("employeeNo"))){
                find.markBegin().like(jsonObject,"exeEmployeeNo").or()
                        .eq(jsonObject,"employeeNo").markEnd().and();
            }
        }else {
            Boolean bool = Boolean.valueOf(active);
            if (bool) {
                if (Objects.nonEmpty(jsonObject.getString("attnEmployeeNo"))) {
                    find.like(jsonObject, "attnEmployeeNo");
                }
            }else{
                if (Objects.nonEmpty(jsonObject.getString("employeeNo"))) {
                    find.markBegin().like(jsonObject, "exeEmployeeNo").or()
                            .eq(jsonObject, "employeeNo").markEnd().and();
                }
            }
        }

        Page<Repairs> page = find.eq("deleted", false)
                .order("createTime", "desc")
                .page(jsonObject).exe();
        List<Repairs> list = page.getList();
        for (Repairs repairs : list) {
            setOtherProperty(token.getCompanyNo(), repairs);
        }
        return page;
    }

    @Bean(copy = true)
    @ReqMapping("/update")
    public Object update(Token token, JSONObject jsonObject, Repairs repairs) throws Exception {
        setProperty(jsonObject, repairs, token.getCompanyNo());
        jdbcSession.updateById(repairs);
        return Result.success();
    }

    @ReqMapping("/get")
    public Repairs get(Token token, String id) throws Exception {
        Repairs item = Pool.get(Repairs.class, id);
        if (Objects.isNull(item)) {
            return null;
        }
        setOtherProperty(token.getCompanyNo(), item);
        return item;
    }

    @ReqMapping("/getRoll")
    public List<RollOutDetail> getRoll(String id) {
        return jdbcSession.findArray(RollOutDetail.class)
                .eq("repairsId", id)
                .order("createTime", "desc").exe();
    }

    @ReqMapping("/remark")
    public Object remark(Token token, JSONObject jsonObject) throws Exception {
        String orderId = jsonObject.getString("repairsId");

        Remark remark = Pool.newInstance(Remark.class);
        remark.setRemarkNameId(token.getUuid());
        JSONObject employeeJSONObject = getEmployeeById(token.getCompanyNo(), token.getUuid());
        remark.setRemarkName(employeeJSONObject.getString("name"));
        remark.setContent(jsonObject.getString("content"));
        remark.setOrderId(orderId);
        jdbcSession.insert(remark);

        // 记录操作
        jsonObject.put("userId", token.getUuid());
        jsonObject.put("companyNo", token.getCompanyNo());
        RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
        newRollOutDetail.setRemark("备注了");
        jdbcSession.insert(newRollOutDetail);

        // 发送公众号模板消息
        threadPool.execute(() -> {
            try {
                sendMessageUtils.sendWeChatMessageTemplate(jsonObject.getString("companyNo"), Pool.get(Repairs.class, orderId), 0);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发送公众号模板消息出错: {}", e);
            }
        });

        return Result.success();
    }

    @ReqMapping("/get/remarkList")
    public List<Remark> remarkList(String id){
        return jdbcSession.findArray(Remark.class)
                .eq("orderId", id)
                .order("createTime", "desc").exe();
    }

    @ReqMapping("/cancel")
    public Object cancel(Token token, JSONObject jsonObject) throws Exception {
        String id = jsonObject.getString("id");
        Repairs repairs = Pool.get(Repairs.class, id);

        if (repairs == null) {
            return Result.error(0, "对象不存在");
        }

        repairs.setRepairsStatus(RepairsStatus.CANCEL);
        jdbcSession.updateById(repairs);

        jsonObject.put("repairsId", id);
        jsonObject.put("userId", token.getUuid());
        jsonObject.put("companyNo", token.getCompanyNo());
        RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
        newRollOutDetail.setRemark("取消了工单");
        jdbcSession.insert(newRollOutDetail);

        return Result.success(repairs);
    }

    @ReqMapping("/delete")
    public Object delete(JSONObject jsonObject) {
        String id = jsonObject.getString("id");
        Repairs repairs = Pool.get(Repairs.class, id);

        if (repairs == null) {
            return Result.error(0, "对象不存在");
        }
        repairs.setDeleted(true);
        jdbcSession.updateById(repairs);
        return Result.success(repairs);
    }

    @ReqMapping("/finish")
    public Object finish(Token token, JSONObject jsonObject) throws Exception {
        String id = jsonObject.getString("id");
        Repairs repairs = Pool.get(Repairs.class, id);
        if (repairs == null) {
            return Result.error(0, "对象不存在");
        }

        repairs.setProcessingResults(jsonObject.getString("processingResults"));
        JSONArray resultsImageIds = jsonObject.getJSONArray("resultsImageIds");
        List<String> list = new ArrayList<>();
        resultsImageIds.forEach(images->{
            list.add((String) images);
        });
        repairs.setResultsImageIds(list);

        repairs.setCompleteTime(LocalDateTime.now());
        repairs.setRepairsStatus(RepairsStatus.EVALUATION);

        jdbcSession.updateById(repairs);

        jsonObject.put("repairsId", id);
        jsonObject.put("userId", token.getUuid());
        jsonObject.put("companyNo", token.getCompanyNo());
        RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
        newRollOutDetail.setRepairsId(jsonObject.getString("id"));
        newRollOutDetail.setRemark("完结了");
        jdbcSession.insert(newRollOutDetail);

        // 发送公众号模板消息
        threadPool.execute(() -> {
            try {
                sendMessageUtils.sendWeChatMessageTemplate(token.getCompanyNo(), repairs,2);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发送公众号模板消息出错：{}", e);
            }
        });

        List<String> empIds = new ArrayList<>();
        getEmployeeListByIds(token.getCompanyNo(), repairs.getAttnEmployeeNo()).forEach(object->{
            empIds.add(((JSONObject) object).getString("id"));
        });
        String title = "您的" + repairs.getType().getDesc() + "已经处理完成！";

        // 发送企业微信模板消息
        threadPool.execute(() -> {
            try {
                sendMessageUtils.sendEnterpriseWeChatMessageTemplate(repairs, title, String.join("|", empIds), token.getCompanyNo());
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发送企业微信消息模板异常: {}", e);
            }
        });

        return Result.success(repairs);
    }

    @ReqMapping("/change")
    public Object change(Token token, JSONObject jsonObject) throws Exception {
        String id = jsonObject.getString("id");
        Repairs repairs = getRepairsById(id);
        if (Objects.isNull(repairs)) {
            return Result.error(0, "不可转单");
        }

        String exeChange = jsonObject.getString("exeChange");
        List<String> exeEmployeeNo = repairs.getExeEmployeeNo();
        exeEmployeeNo.remove(token.getUuid());
        exeEmployeeNo.add(exeChange);
        repairs.setExeEmployeeNo(exeEmployeeNo);

        // 关注人
        List<String> attnEmployeeNo = repairs.getAttnEmployeeNo();
        attnEmployeeNo.add(token.getUuid());
        repairs.setAttnEmployeeNo(attnEmployeeNo);

        jdbcSession.updateById(repairs);

        jsonObject.put("repairsId", id);
        jsonObject.put("userId", token.getUuid());// todo id
        jsonObject.put("companyNo", token.getCompanyNo());
        RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
        newRollOutDetail.setNewEmployeeNo(exeChange);
        newRollOutDetail.setNewEmployeeName(jsonObject.getString("exeName"));
        newRollOutDetail.setRemark("转执行人");
        jdbcSession.insert(newRollOutDetail);

        JSONArray employeeJSONArray =getEmployeeListByIds(token.getCompanyNo(), exeEmployeeNo);
        employeeJSONArray.addAll(getEmployeeListByIds(token.getCompanyNo(), attnEmployeeNo));
        // 发送企业微信消息模板
        sendMessageTemplateByEmployees(repairs, employeeJSONArray, token.getCompanyNo());
        return Result.success();
    }

    @ReqMapping("/again")
    public Object again(Token token, JSONObject jsonObject) throws Exception {
        String id = jsonObject.getString("id");
        Repairs repairs = getRepairsById(id);
        if (Objects.isNull(repairs)) {
            return Result.error(0, "不可转单");
        }

        // 执行人
        String exeChange = jsonObject.getString("exeChange");
        List<String> exeList = new ArrayList<>();
        if (Objects.nonEmpty(exeChange)) {
            exeList.add(exeChange);
            repairs.setExeEmployeeNo(exeList);

            //记录操作日志
            jsonObject.put("repairsId", id);
            jsonObject.put("userId", token.getUuid());
            jsonObject.put("companyNo", token.getCompanyNo());
            RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
            newRollOutDetail.setNewEmployeeNo(exeChange);
            newRollOutDetail.setNewEmployeeName(jsonObject.getString("exeName"));
            newRollOutDetail.setRemark("重新指派执行人");
            jdbcSession.insert(newRollOutDetail);
        }

        // 关注人
        String attnChange = jsonObject.getString("attnChange");
        List<String> attnList = new ArrayList<>();
        if(Objects.nonEmpty(attnChange)){
            attnList.add(attnChange);
            repairs.setAttnEmployeeNo(attnList);

            //记录操作日志
            jsonObject.put("repairsId", id);
            jsonObject.put("userId", token.getUuid());
            jsonObject.put("companyNo", token.getCompanyNo());
            RollOutDetail newRollOutDetail = getNewRollOutDetail(jsonObject);
            newRollOutDetail.setNewEmployeeNo(attnChange);
            newRollOutDetail.setNewEmployeeName(jsonObject.getString("attnName"));
            newRollOutDetail.setRemark("重新指派关注人");
            jdbcSession.insert(newRollOutDetail);
        }
        jdbcSession.updateById(repairs);


        JSONArray employeeJSONArray =getEmployeeListByIds(token.getCompanyNo(), exeList);
        employeeJSONArray.addAll(getEmployeeListByIds(token.getCompanyNo(), attnList));
        // 发送企业微信消息模板
        sendMessageTemplateByEmployees(repairs, employeeJSONArray, token.getCompanyNo());

        return Result.success();
    }

    @ReqMapping("/accept")
    public Object acceptRepairs(Token token, JSONObject jsonObject) throws Exception {
        String id = jsonObject.getString("id");
        Repairs repairs = Pool.get(Repairs.class, id);
        if (Objects.isNull(repairs)) {
            return Result.error(0, "对象不存在");
        }

        repairs.setRepairsStatus(RepairsStatus.PROCESSING);
        repairs.setEmployeeNo(token.getUuid());

        // 移除执行人
        List<String> exeEmployeeNo = repairs.getExeEmployeeNo();
        exeEmployeeNo.remove(token.getUuid());

        // 添加关注人
        List<String> attnEmployeeNo = repairs.getAttnEmployeeNo();
        attnEmployeeNo.addAll(exeEmployeeNo);

        repairs.setExeEmployeeNo(null);
        repairs.setAttnEmployeeNo(attnEmployeeNo);

        repairs.setAssignTime(LocalDateTime.now());

        jdbcSession.updateById(repairs);

        // 记录操作
        jsonObject.put("repairsId", id);
        jsonObject.put("userId", token.getUuid());
        jsonObject.put("companyNo", token.getCompanyNo());
        RollOutDetail rollOutDetail = getNewRollOutDetail(jsonObject);
        rollOutDetail.setRemark("受理了");
        jdbcSession.insert(rollOutDetail);

        //发公众号模板消息
        threadPool.execute(() -> {
            try {
                sendMessageUtils.sendWeChatMessageTemplate(token.getCompanyNo(), repairs, 1);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发公众号模板消息出错：{}", e);
            }
        });

        JSONArray employeeJSONArray = getEmployeeListByIds(token.getCompanyNo(), repairs.getAttnEmployeeNo());
        sendMessageTemplateByEmployees(repairs, employeeJSONArray, token.getCompanyNo());

        return Result.success(repairs);
    }

    /**
     * 通过小区id获取小区
     *
     * @param companyNo
     * @param id
     * @return
     * @throws Exception
     */
    private JSONObject getCommunityById(String companyNo, String id) throws Exception {
        JSONObject object = doveClient.post("/basic/community/service/get", (http) -> {
            http.addHeader("companyNo", companyNo);
            http.addParam("id", id);
        });

        if (object.getInteger("code") == 200) {
            return object.getJSONObject("data");
        } else {
            logger.error("{}", object.getString("message"));
            return new JSONObject();
        }
    }

    /**
     * 设置其他属性
     * @param repairs
     */
    private void setOtherProperty(String companyNo, Repairs repairs) throws Exception {
        RepairsType repairsType = Pool.get(RepairsType.class, repairs.getTypeId());

        if(Objects.nonEmpty(repairs.getEmployeeNo())){
            JSONObject employeeJSONObject = getEmployeeById(companyNo, repairs.getEmployeeNo());
            repairs.setExeRoleNames(employeeJSONObject.getString("name"));
        }else{
            if(Objects.nonEmpty(repairs.getExeEmployeeNo())){
                JSONArray employeeListJSONArray = getEmployeeListByIds(companyNo, repairs.getExeEmployeeNo());
                List<String> empNames = new ArrayList<>();
                employeeListJSONArray.forEach(obj -> {
                    JSONObject jsonObject = (JSONObject) obj;
                    empNames.add(jsonObject.getString("name"));
                });
                repairs.setExeRoleNames(String.join(",", empNames));
            }
        }
        if(Objects.nonEmpty(repairs.getAttnEmployeeNo())){
            JSONArray employeeListJSONArray = getEmployeeListByIds(companyNo, repairs.getAttnEmployeeNo());
            List<String> empNames = new ArrayList<>();
            employeeListJSONArray.forEach(obj -> {
                JSONObject jsonObject = (JSONObject) obj;
                empNames.add(jsonObject.getString("name"));
            });
            repairs.setAttnRoleNames(String.join(",", empNames));
        }
        repairs.setTime(RepairsUtils.jointTime(repairsType));
        repairs.setCountdown(RepairsUtils.getCountdown(repairs));

        JSONObject communityJSONObject = getCommunityById(companyNo, repairs.getCommunityNo());
        repairs.setCommunityName(communityJSONObject.getString("name"));
    }

    /**
     * 设置属性
     * @param jsonObject
     * @return
     */
    private Repairs setProperty(JSONObject jsonObject, Repairs repairs, String companyNo) throws Exception {
        repairs.setFaultPosition(jsonObject.getString("faultPosition"));
        repairs.setContactName(jsonObject.getString("contactName"));
        repairs.setContactMobile(jsonObject.getString("contactMobile"));

        String typeId = jsonObject.getString("typeId");
        if (!Objects.equal(typeId, repairs.getTypeId())) {
            repairs.setTypeId(typeId);
            RepairsType repairsType = Pool.get(RepairsType.class, typeId);
            repairs.setTypeName(repairsType.getName());

            JSONObject obj = doveClient.post("/flow/service/role/get/employee/ByDepartmentChildren", (http) -> {
                http.addHeader("companyNo", companyNo);
                http.addParam("communityNo", repairs.getCommunityNo());
                http.addParam("roleId", repairsType.getExeRoleId());
            });
            JSONArray exeEmployees = obj.getJSONArray("data");
            List<String> exeList = new ArrayList<>();
            exeEmployees.forEach(object->{
                exeList.add(((JSONObject) object).getString("id"));
            });
            repairs.setExeEmployeeNo(exeList);

            JSONObject resObj = doveClient.post("/flow/service/role/get/employee/ByDepartmentChildren", (http) -> {
                http.addHeader("companyNo", companyNo);
                http.addParam("communityNo", repairs.getCommunityNo());
                http.addParam("roleId", repairsType.getAttnRoleId());
            });
            JSONArray attnEmployee = resObj.getJSONArray("data");
            List<String> attnList = new ArrayList<>();
            attnEmployee.forEach(object->{
                attnList.add(((JSONObject) object).getString("id"));
            });
            repairs.setAttnEmployeeNo(attnList);

        }

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String appointmentStartTime = jsonObject.getString("appointmentStartTime");
        repairs.setAppointmentStartTime(LocalDateTime.parse(appointmentStartTime, fmt));

        String appointmentEndTime = jsonObject.getString("appointmentEndTime");
        repairs.setAppointmentEndTime(LocalDateTime.parse(appointmentEndTime, fmt));

        repairs.setDetail(jsonObject.getString("detail"));

        JSONArray imageIds = jsonObject.getJSONArray("imageIds");
        if(Objects.nonNull(imageIds)){
            List<String> ids = new ArrayList<>();
            imageIds.forEach(id->{
                ids.add((String)id);
            });
            repairs.setImageIds(ids);
        }

        return repairs;
    }

    /**
     * 获取处理进度对象
     * @return
     */
    private RollOutDetail getNewRollOutDetail(JSONObject jsonObject) throws Exception {
        RollOutDetail rollOutDetail = Pool.newInstance(RollOutDetail.class);
        rollOutDetail.setRepairsId(jsonObject.getString("repairsId"));
        rollOutDetail.setOldEmployeeNo(jsonObject.getString("userId"));
        JSONObject employeeJSONObject = getEmployeeById(jsonObject.getString("companyNo"), jsonObject.getString("userId"));
        rollOutDetail.setOldEmployeeName(employeeJSONObject.getString("name"));

        return rollOutDetail;
    }

    /**
     *  通过id获取待处理投诉/报修单
     *
     * @param id
     * @return
     */
    private Repairs getRepairsById(String id) {
        Repairs repairs = Pool.get(Repairs.class, id);
        if(!Objects.equal(repairs.getRepairsStatus(), RepairsStatus.PENDING)){
            return null;
        }
        return repairs;
    }

    /**
     *  通过员工集合获取userId发送企业微信消息模板
     *
     * @param repairs
     * @param employees
     */
    private void sendMessageTemplateByEmployees(Repairs repairs, JSONArray employees, String companyNo) {
        if (Objects.nonEmpty(employees)) {
            List<String> empIds = new ArrayList<>();
            employees.forEach(object -> {
                empIds.add(((JSONObject) object).getString("id"));
            });

            sendMessageTemplateByUserId(repairs, String.join("|", empIds), companyNo);
        }
    }

    /**
     *  通过userId发送企业微信消息模板
     *
     * @param repairs
     * @param userId
     */
    private void sendMessageTemplateByUserId(Repairs repairs, String userId, String companyNo) {
        String title = "您有新的" + repairs.getType().getDesc() + ",请及时处理！";
        // 发送企业微信消息模板
        threadPool.execute(() -> {
            try {
                sendMessageUtils.sendEnterpriseWeChatMessageTemplate(repairs, title, userId, companyNo);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发送企业微信消息模板异常: {}", e);
            }
        });
    }

    /**
     * 通过id获取员工
     *
     * @param companyNo
     * @param id
     * @return
     * @throws Exception
     */
    private JSONObject getEmployeeById(String companyNo, String id) throws Exception {
        JSONObject object = doveClient.post("/basic/employee/service/get", (http) -> {
            JSONObject body = new JSONObject();
            body.put("id", id);

            http.addHeader("companyNo", companyNo);
            http.setBody(body.toString());
        });
        if (object.getInteger("code") == 200) {
            return object.getJSONObject("data");
        } else {
            logger.error("{}", object.getString("message"));
            return new JSONObject();
        }
    }

    /**
     * 通过ids获取员工
     *
     * @param companyNo
     * @param ids
     * @return
     * @throws Exception
     */
    private JSONArray getEmployeeListByIds(String companyNo, List<String> ids) throws Exception {
        if (Objects.isEmpty(ids)) {
            return new JSONArray();
        }
        JSONObject object = doveClient.post("/basic/employee/service/list", (http) -> {  //todo 地址
            http.addHeader("companyNo", companyNo);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", ids);
            http.setBody(jsonObject.toString());
        });

        if (object.getInteger("code") == 200) {
            return object.getJSONArray("data");
        } else {
            logger.error("{}", object.getString("message"));
            return new JSONArray();
        }
    }

}
